package com.minisoft.utils.thread;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.concurrent.*;

/**
 * @author JueSu
 * @description: 定时任务测试类
 * @date 2022/5/1 16:24
 */
@Slf4j
public class ScheduleRetry {

    private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);

    /**
     * 增加一个需要做的任务，任务返回true，则执行成功
     * @param task 需要做的任务
     * @param maxRetry 最大执行次数
     * @param period 间隔时间，单位秒
     */
    public static void addTask(Callable<Boolean> task,int maxRetry,int period) {
        executorService.schedule(new RetryRunner(task,maxRetry,period),period, TimeUnit.SECONDS);
    }

    /**
     * 增加一个需要做的任务，默认每5秒执行一次，最多5次，任务返回true，则执行成功
     * @param task 需要做的任务
     */
    public static void addTask(Callable<Boolean> task) {
        executorService.schedule(new RetryRunner(task,5,5),5, TimeUnit.SECONDS);
    }

    static class RetryRunner implements Runnable {

        int period;
        int retry = 0;
        int maxRetry;

        Callable<Boolean> task;

        public RetryRunner(Callable<Boolean> task, int maxRetry, int period) {
            this.maxRetry = maxRetry;
            this.task = task;
            this.period = period;
        }

        boolean finished = false;

        boolean isContinue() {
            return !finished && (retry++) < maxRetry;
        }

        public void run() {
            if (isContinue()) {
                log.info("do task for {} ,retry = {}",task.toString(),retry);
                try {
                    finished = task.call();
                } catch (Exception e) {
                    log.error("do task error for " + task.toString() + ",try next time",e);
                }
                //延迟5秒后继续执行
                executorService.schedule(this,period, TimeUnit.SECONDS);
            } else {
                log.info("{} to finish task for {}",finished ? "success" : "failed",task.toString());
            }
        }
    }
}
